using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

using System.Diagnostics;
using System.IO;
using System.Text;

using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.ApplicationPages;


namespace TweakSP.Web.Admin
{
    public partial class TweakSP_ViewLogs : GlobalAdminPageBase
    {

        const int MAX_LENGTH = 307200;      // 300k should be good
        const int MAX_LOG_SIZE = 31457280;  // Honestly... over 30MB of logs.  Not going there...

        protected Literal logViewHeader;
        protected SPGridView grdViewLogs;

        private string LogLocation
        {
            get
            {
                return Microsoft.SharePoint.Administration.SPDiagnosticsService.Local.LogLocation;
            }
        }

        private FileInfo _currentLog;
        private FileInfo CurrentLog
        {
            get
            {
                if (_currentLog == null)
                {
                    DirectoryInfo dir = new DirectoryInfo(LogLocation);
                    foreach (FileInfo file in dir.GetFiles("*.log"))
                    {
                        if (_currentLog == null)
                        {
                            _currentLog = file;
                        }
                        if (_currentLog.LastWriteTime < file.LastWriteTime)
                        {
                            _currentLog = file;
                        }
                    }
                }
                return _currentLog;
            }
        }

        private string ReadLogTail()
        {
            if (CurrentLog.Length > MAX_LOG_SIZE)
            {
                //TODO: Fail nicer still?
                throw new Exception("Your log file is gynormous!  Consider decreasing the 'Number of minutes to use a log file' setting in <a href='/_admin/metrics.aspx'>Central Administration</a>.");
            }

            using (System.IO.FileStream fStream = CurrentLog.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
            {
                int streamLength = (int)fStream.Length;
                int startIndex = 0;
                int readLength = 0;

                if (fStream.Length > MAX_LENGTH)
                {
                    startIndex = streamLength - MAX_LENGTH;
                    readLength = MAX_LENGTH;
                }
                else
                {
                    readLength = streamLength;
                }
                Debug.WriteLine("streamLength: " + streamLength.ToString());
                Debug.WriteLine("startIndex: " + startIndex.ToString());
                Debug.WriteLine("readLength: " + readLength.ToString());

                byte[] tailBytes = new byte[streamLength];

                Debug.WriteLine("fStream.Read");
                fStream.Read(tailBytes, startIndex, readLength);

                fStream.Close();

                using (MemoryStream tailStream = new MemoryStream(tailBytes))
                {
                    using (StreamReader tailReader = new StreamReader(tailStream))
                    {
                        Debug.WriteLine("tailReader.ReadToEnd");
                        string tail = tailReader.ReadToEnd();

                        tailReader.Close();
                        tailStream.Close();

                        return tail;
                    }
                }
            }
        }


        private string LogToHtml(string log)
        {
            return log.Replace("\n", "<br />\n");
        }


        private void LogToSPGridView(SPGridView grid, string log)
        {
            string[] logEntries = log.Split('\n');

            if (logEntries.Length > 1)
            {
                System.Data.DataTable logTbl = new DataTable();

                PrepareTableAndGrid(ref grid, ref logTbl);

                for (int x = 1; x < logEntries.Length; x++)     // Skip the first row
                {
                    logTbl.Rows.Add(logEntries[x].Split('\t'));
                }

                grid.DataSource = logTbl;
                grid.DataBind();
            }

        }


        private void PrepareTableAndGrid(ref SPGridView grid, ref DataTable tbl)
        {
            string[] logColumns = new string[] { "Timestamp", "Process", "TID", "Area", "Category", "EventID", "Level", "Message", "Correlation" };
            SPBoundField gridField;

            foreach (string column in logColumns)
            {
                tbl.Columns.Add(column);            // Add the column to our datatable
                gridField = new SPBoundField();     // Create the new SPGridView Field
                gridField.HeaderText = column;
                gridField.DataField = column;

                grid.Columns.Add(gridField);
            }
        }


        protected override void OnLoad(EventArgs e)
        {
            StringBuilder message = new StringBuilder();

            //DirectoryInfo dir = new DirectoryInfo(LogLocation);

            //message.Append("Log location: " + LogLocation + "<br />");
            //message.Append("Logs found: <br /><br />");

            //foreach (FileInfo file in dir.GetFiles("*.log"))
            //{
            //    message.Append(file.Name + "<br />");
            //}


            if (CurrentLog != null)
            {
                message.Append("Log location: " + CurrentLog.FullName + "<br />");

                message.Append("<br /><br />");

                try
                {
                    string log = ReadLogTail();

                    LogToSPGridView(grdViewLogs, log);
                }
                catch (Exception ex)
                {
                    message.Append("<br />Error:<br />" + ex.Message);
                }
            }

            logViewHeader.Text = message.ToString();

        }

    }
}
